package com.ray.magicBlock.spring;

import com.ray.magicBlock.BlockConfig;
import com.ray.magicBlock.Strategy;
import com.ray.magicBlock.anno.Block;
import com.ray.magicBlock.Utils;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.reflections.scanners.*;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Set;


/**
 * @author bo shen
 * @Description: 模块对象注册工厂
 * @Class: BlockBeanFactory
 * @Package com.ray.magicBlock.spring
 * @date 2019/10/9 19:11
 * @company <p></p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Component
@Slf4j
public class BlockBeanFactory implements ApplicationContextAware{

    @Autowired
    private BlockConfig blockConfig;

    Reflections reflections = null;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        String path = "";
        if(blockConfig != null){
            path = blockConfig.getPackages();
        }
        log.info("加载路劲:{}",path);
        try {
            ConfigurationBuilder configBuilder =
                    new ConfigurationBuilder()
                            .filterInputsBy(new FilterBuilder().includePackage(path))
                            .setUrls(ClasspathHelper.forPackage(path))
                            .setScanners(
                                    new SubTypesScanner()
                            );
             reflections = new Reflections(configBuilder);
        }catch (Exception e){
            log.info("读取其他类型文件异常");
        }
        log.info("模块对象工厂启动------注册模块对象。");
        register(applicationContext);
        log.info("模块对象工厂启动------注册模块对象完成");
    }

    /**
     * 注册
     * @param applicationContext
     */
    private void register(ApplicationContext applicationContext) {
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
        Set<Class<? extends Strategy>> subTypes = reflections.getSubTypesOf(Strategy.class);
        //单个加载
       for(Class<?> clazz :subTypes){
           if(!clazz.isAnnotationPresent(Block.class)){
               continue;
           }
           Block block = clazz.getAnnotation(Block.class);
           log.info("加载策略类:{},分组：{}，策略：{}",clazz.getName(),block.group(),block.strategy());
           BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
           BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
           BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) configurableApplicationContext.getBeanFactory();
           String beanName = Utils.getBeanName(block.group(),block.strategy());
           log.info("注册bean:{}",beanName);
           beanFactory.registerBeanDefinition(beanName, beanDefinition);
       }
        log.info("加载策略类完成");
    }
}
